/*
 ============================================================================
 Name        : insParser.c
 Author      :
 Version     :
 Copyright   : Your copyright notice
 Description : Parser a Xml file which contains the instruction attributes
 ============================================================================
 */

#include "insParser.h"
#include <string.h>
#include <debug.h>
#include <ctype.h>


/*! \fn findProperty(xmlAttr* a_attrb, char*name)
 \brief Find in a_attrb the property name and returns its content
 \param a_attrb Xml node where property its gonna be search
 \param name Property searched
 */
char* findProperty(xmlAttr* a_attrb, char*name) {

	xmlAttr *cur_attrb = NULL;

	for (cur_attrb = a_attrb; cur_attrb; cur_attrb = cur_attrb->next)
	{
		if (strcmp((char*) cur_attrb->name, name) == 0)
		{
			return (char*) cur_attrb->children->content;
		}
	}
	return (char*) 0;
}

/*! \fn getTag(xmlNode * a_node, char* tagName, xmlNode **myRet)
 \brief Find in a_attrb the property name and returns its content
 \param a_attrb Xml node where property its gonna be search
 \param name Property searched
 */
char getTag(xmlNode * a_node, char* tagName, xmlNode **myRet) {

	xmlNode *cur_node = NULL;

	for (cur_node = a_node; cur_node; cur_node = cur_node->next) {


		if (strcmp((char*) cur_node->name, tagName) == 0)
		{
			PRINT_DEBUG(DEBUG_INS_TAG, "TAG: %s\n", cur_node->name);
			*myRet = cur_node;
			return 1;
		}
		if (getTag(cur_node->children, tagName, myRet)) {
			return 1;
		}
	}
	return 0;
}


char getTagProperty(xmlNode * a_node,
					char* tagName,
					char* propertyName,
					char* propertyValue,
					xmlNode **myRet)
{
	xmlNode *cur_node = NULL;

	char * myChar;

	for (cur_node = a_node; cur_node; cur_node = cur_node->next)
	{

		if (strcmp((char*) cur_node->name, tagName) == 0)
		{
			if (strcmp(	myChar = findProperty(	cur_node->properties,
												propertyName),
						propertyValue) == 0)
			{
				PRINT_DEBUG(DEBUG_INS_PROPERTIES,
							"Property: %s = %s\n",
							propertyName, myChar);
				*myRet = cur_node;
				return 1;
			}
		}
		if (getTagProperty(	cur_node->children,
							tagName,
							propertyName,
							propertyValue,
							myRet))
		{
			return 1;
		}
	}
	return 0;

}

char findOneByteOpcode(unsigned char op) {
	xmlDoc *doc = NULL;
	xmlNode *root_element = NULL;
	xmlNode *myElement = NULL;

	char stringOpcode[5];
	sprintf(stringOpcode, "%02x", op);
	convertToUpperCase(stringOpcode);
	/*parse the file and get the DOM */
	doc = xmlReadFile(INSTRUCTION_REF_FILE, NULL, 0);

	if (doc == NULL) {
		printf("error: could not parse file %s\n", INSTRUCTION_REF_FILE);
		assert(0);
	}

	/*Get the root element node */
	root_element = xmlDocGetRootElement(doc);


	if (getTagProperty(	root_element,
						"pri_opcd",
						"value",
						stringOpcode,
						&myElement))
	{
		xmlNode *myElement3 = NULL;
		getTag(myElement->children, "grp1", &myElement3);
		if (strcmp((char*) myElement3->children->content, "prefix") == 0)
		{
			return STATUS_ERROR;
		}

		return STATUS_SUCCESS;
	}

	xmlFreeDoc(doc);
	xmlCleanupParser();

	return STATUS_ERROR;
}


char findTwoByteOpcode(unsigned char op)
{
	xmlDoc *doc = NULL;
	xmlNode *root_element = NULL;
	xmlNode *myElement = NULL;

	char stringOpcode[5];
	sprintf(stringOpcode, "%02x", op);
	convertToUpperCase(stringOpcode);
	/*parse the file and get the DOM */
	doc = xmlReadFile(INSTRUCTION_REF_FILE, NULL, XML_PARSE_NOBLANKS);

	if (doc == NULL) {
		printf("error: could not parse file %s\n", INSTRUCTION_REF_FILE);
		assert(0);
	}

	/*Get the root element node */
	root_element = xmlDocGetRootElement(doc);


	if (getTagProperty(	root_element->children->next,
						"pri_opcd",
						"value",
						stringOpcode,
						&myElement))
	{
		xmlNode *myElement3 = NULL;

		getTag(myElement->children, "grp1", &myElement3);
		if (strcmp((char*) myElement3->children->content, "prefix") == 0)
		{
			return STATUS_ERROR;
		}

		return STATUS_SUCCESS;
	}

	xmlFreeDoc(doc);
	xmlCleanupParser();

	return STATUS_ERROR;
}

//todo remove dependencies OPCODE_PROPERTIES
char getOpcodeAtributes(unsigned char op, OPCODE_PROPERTIES* opProp) {
	xmlDoc *doc = NULL;
	xmlNode *root_element = NULL;
	xmlNode *myElement = NULL;
	xmlNode *syntax = NULL;
	xmlNode *operand = NULL;
	xmlNode *operandTags = NULL;

	UINT8 operandNumber = 0;

	//xmlNode *myElement2 = NULL;

	char stringOpcode[5];
	sprintf(stringOpcode, "%02x", op);
	convertToUpperCase(stringOpcode);

	PRINT_DEBUG(DEBUG_INS_OPCODE_ATTRIBUTES,
				"Getting attributes for opcode: %s\n",
				stringOpcode);

	/*parse the file and get the DOM */
	doc = xmlReadFile(INSTRUCTION_REF_FILE, NULL, XML_PARSE_NOBLANKS);

	if (doc == NULL) {
		printf("error: could not parse file %s\n", INSTRUCTION_REF_FILE);
		assert(0);
	}
	/*Get the root element node */
	root_element = xmlDocGetRootElement(doc);

	if (getTagProperty(	root_element,
						"pri_opcd",
						"value",
						stringOpcode,
						&myElement))
	{

		//
		//find syntax tag
		//
		getTag(myElement->children, "syntax", &syntax);


		if (syntax->children)		//mnemonic

		{

			strcpy(	opProp->mnemonic,
					(INT8*) syntax->children->children->content);
		}
		operand = syntax->children->next;

		while (operand)
		{


			if (getTag(operand->children, "a", &operandTags))
			{
				PRINT_DEBUG(DEBUG_INS_PROPERTIES,
							"a: %s\n",
							operandTags->children->content);
				strcpy(	opProp->operand_at[operandNumber].a,

						(INT8*) operandTags->children->content);
			}

			if (getTag(operand->children, "t", &operandTags))
			{
				PRINT_DEBUG(DEBUG_INS_PROPERTIES,
							"t: %s\n",
							operandTags->children->content);
				strcpy(	opProp->operand_at[operandNumber].t,

						(INT8*) operandTags->children->content);
			}


			if (*opProp->operand_at[operandNumber].a != 0
					|| *opProp->operand_at[operandNumber].t != 0)
			{

				operandNumber++;
			}//todo check patch
			else
			{
				opProp->operand_at[operandNumber].a[0] = 'H';
				opProp->operand_at[operandNumber].a[1] = '1';
				*opProp->operand_at[operandNumber].t = 'b';
				PRINT_DEBUG(DEBUG_INS_PROPERTIES,"a: %s\n","H1");
				PRINT_DEBUG(DEBUG_INS_PROPERTIES,"t: %c\n",'b');

				operandNumber++;
			}

			operand = operand->next;

		}

		return STATUS_SUCCESS;
	}

	xmlFreeDoc(doc);
	xmlCleanupParser();

	return STATUS_ERROR;
}

void hh() {
	xmlDoc *doc = NULL;
	xmlNode *root_element = NULL;
	xmlNode *myElement = NULL;
	xmlNode *myElement2 = NULL;

	/*
	 * this initialize the library and check potential ABI mismatches
	 * between the version it was compiled for and the actual shared
	 * library used.
	 */

	/*parse the file and get the DOM */
	doc = xmlReadFile(INSTRUCTION_REF_FILE, NULL, 0);

	if (doc == NULL) {
		printf("error: could not parse file %s\n", INSTRUCTION_REF_FILE);
	}

	getTagProperty(root_element, "pri_opcd", "value", "03", &myElement);
	getTag(myElement, "mnem", &myElement2);

	findTwoByteOpcode(0x00);
	//getOpcodeAtributes((unsigned char)0x89,buf);
	//findOpcode((unsigned char)0x66,buf);

	printf("OPCODE: %s\n", myElement2->children->content);
	//myElement = findOpcode(root_element, 0x3);
	//print_element_names(myElement);
	/*free the document */
	xmlFreeDoc(doc);

	/*
	 *Free the global variables that may
	 *have been allocated by the parser.
	 */
	xmlCleanupParser();
}
